/*
 * Created on 08/30/2011 - 11:38 PM
 */
package sembr.vtk.mesh;

import sembr.vtk.data.input.VtkDataReceiver;
import vtk.*;

/**
 *
 * @author Adriano
 */
public class VtkMeshGenerator 
{
    private VtkDataReceiver inputData;
    private vtkCamera camera;
    private vtkPanel panel;
    private vtkActor inputActor;
    private vtkActor smallSphereActor;
    private vtkActor pointsInsideActor;
    private vtkActor outlineActor;
    private vtkActor surfaceActor;
    private vtkActor gridActor;
    private vtkActor linesActor;
    private vtkActor cubeActor;
    //private vtkActorCollection actorCollection;
    
    public VtkMeshGenerator()
    {
        LoadVTKLibraries();
        //actorCollection = new vtkActorCollection();
        //VoxelizeDomain();
        //this.PointInsideACell();
        //generateFDTDGrid(-10, 10, -10, 10, -10, 10, 1.00);
        //generateFDTDGrid2(-1, 0, -1, 0, -1, 0, 1.00);
        //visualizeCrossingRays(-50.00, 50.00, 5.00);
        //visualizeFDTDGrid(-2, 2, -2, 2, -2, 2, 1.00);
        setCamera();
        setPanel();
    }
    
    public VtkMeshGenerator(VtkDataReceiver inputData)
    {
        this.inputData = inputData;
        LoadVTKLibraries();
        //actorCollection = new vtkActorCollection();
        //this.VoxelizeDomain();
        //this.PointInsideACell();
        //generateFDTDGrid(-50, 49, -50, 49, -50, 49, 1.00);
        //generateFDTDGrid2(-10, 10, -10, 10, -10, 10, 5.00);
        //visualizeCrossingRays(-10.00, 10.00, 1.00);
        generateFDTDMesh(0.1);
        this.setCamera();
        this.setPanel();
    }
    
    public final void VoxelizeDomain()
    {
        vtkSphereSource bigSphere = new vtkSphereSource();
        bigSphere.SetCenter(0.0, 0.0, 0.0);
        bigSphere.SetRadius(4);
        bigSphere.SetThetaResolution(20);
        bigSphere.SetPhiResolution(20);
        bigSphere.Update();
        
        inputData.getPolyData().GetBounds();
              
        double bounds[] = new double[6];
        //bounds = bigSphere.GetOutput().GetBounds();
        bounds = inputData.getPolyData().GetBounds();
                      
        for (int k = 0; k < 6; k = k + 2)
        {
            double range = bounds[k + 1] - bounds[k];
            bounds[k] = bounds[k] - (0.1 * range);
            bounds[k + 1] = bounds[k + 1] + (0.1 * range);
        }
        
        vtkVoxelModeller voxelModel = new vtkVoxelModeller();
        voxelModel.SetSampleDimensions(100, 100, 100);
        voxelModel.SetModelBounds(bounds);
        voxelModel.SetScalarTypeToDouble();        
        voxelModel.SetMaximumDistance(0.1);
        voxelModel.SetInput(inputData.getPolyData());
        
        
        vtkMarchingCubes surface = new vtkMarchingCubes();
        surface.SetInputConnection(voxelModel.GetOutputPort());
        surface.ComputeNormalsOn();
        
        surface.SetValue(0, 0.5);
                        
        vtkPolyDataMapper surfaceMapper = new vtkPolyDataMapper();
        surfaceMapper.SetInputConnection(surface.GetOutputPort());
                
        surfaceActor = new vtkActor();
        surfaceActor.SetMapper(surfaceMapper);
        surfaceActor.GetProperty().SetColor(10, 10, 10);        
    }
    
    public final void PointInsideACell()
    {
        vtkSphereSource bigSphere = new vtkSphereSource();
        bigSphere.SetCenter(0.0, 0.0, 0.0);
        bigSphere.SetRadius(4);
        bigSphere.SetThetaResolution(20);
        bigSphere.SetPhiResolution(20);
        bigSphere.Update();
        
        vtkPolyDataMapper bigSphereMap = new vtkPolyDataMapper();
        bigSphereMap.SetInput(bigSphere.GetOutput());
        
        inputActor = new vtkActor();
        inputActor.SetMapper(bigSphereMap);
        inputActor.GetProperty().SetOpacity(0.5);
        
        vtkSphereSource smallSphere = new vtkSphereSource();
        smallSphere.SetCenter(1.0, 2.0, 1.0);
        smallSphere.SetRadius(2);
        smallSphere.SetThetaResolution(20);
        smallSphere.SetPhiResolution(20);
        smallSphere.Update();
        
        vtkPolyDataMapper smallSphereMap = new vtkPolyDataMapper();
        smallSphereMap.SetInput(smallSphere.GetOutput());
        
        smallSphereActor = new vtkActor();
        smallSphereActor.SetMapper(smallSphereMap);
                
        vtkPoints pointsInside = new vtkPoints();
        vtkPolyData dataInside = new vtkPolyData();
               
        vtkDelaunay3D delaunay = new vtkDelaunay3D();
        //delaunay.SetInputConnection(bigSphere.GetOutputPort());
        delaunay.SetInput(bigSphere.GetOutput());
        delaunay.Update();
        
        vtkCellLocator locator = new vtkCellLocator();
        locator.SetDataSet(delaunay.GetOutput());
        locator.BuildLocator();
        
        int n_points = smallSphere.GetOutput().GetPoints().GetNumberOfPoints();
        double[] point = new double[3];
        
        for (int i = 0; i < n_points; i++)
        {
            
            //smallSphere.GetOutput().GetPoint(i, point);
            point = smallSphere.GetOutput().GetPoints().GetPoint(i);         
            
            int cellId = locator.FindCell(point);
            
            
            
            if (cellId >= 0)
            {
                System.out.println("Cell " + cellId + " is inside.");                
                pointsInside.InsertNextPoint(point);
            }
            else
            {
                System.out.println("Outside!");
            }
        }
        
        dataInside.SetPoints(pointsInside);
        
        vtkVertexGlyphFilter vertex = new vtkVertexGlyphFilter();
        vertex.SetInputConnection(dataInside.GetProducerPort());
        
        vtkPolyDataMapper pointsInsideMapper = new vtkPolyDataMapper();
        pointsInsideMapper.SetInputConnection(vertex.GetOutputPort());
        pointsInsideActor = new vtkActor();
        pointsInsideActor.SetMapper(pointsInsideMapper);
        pointsInsideActor.GetProperty().SetPointSize(6);        
        pointsInsideActor.GetProperty().SetColor(1.00, 0.00, 1.00);     
        
        vtkOutlineFilter outline = new vtkOutlineFilter();
        outline.SetInput(bigSphere.GetOutput());
        
        vtkPolyDataMapper outlineMapper = new vtkPolyDataMapper();
        outlineMapper.SetInput(outline.GetOutput());
        
        outlineActor = new vtkActor();
        outlineActor.SetMapper(outlineMapper);
        outlineActor.GetProperty().SetColor(0, 0, 0);
        
        double bounds[] = new double[6];
        bounds = bigSphere.GetOutput().GetBounds();
        
        for (int k = 0; k < 6; k = k + 2)
        {
            double range = bounds[k + 1] - bounds[k];
            bounds[k + 1] = bounds[k + 1] - (0.1 * range);
            bounds[k] = bounds[k] - (0.1 * range);
        }
    }
    
    private void generateFDTDMesh(double resolution)
    { 
        double[] bounds = this.inputData.getPolyData().GetBounds();
        int[] extent1 = new int[bounds.length];
        
        // object´s bounds is rounded
        // initial axes´s values is rounded down and final axes´s is rounded up
        extent1[0] = (int)Math.floor(bounds[0]);
        extent1[1] = (int)Math.ceil(bounds[1]);
        extent1[2] = (int)Math.floor(bounds[2]);
        extent1[3] = (int)Math.ceil(bounds[3]);
        extent1[4] = (int)Math.floor(bounds[4]);
        extent1[5] = (int)Math.ceil(bounds[5]);
        
        int xLength = extent1[1] - extent1[0];
        int yLength = extent1[3] - extent1[2];
        int zLength = extent1[5] - extent1[4];
        
        System.out.println("bound x1: " + bounds[0] + " - extent x1: " + extent1[0]);
        System.out.println("bound x2: " + bounds[1] + " - extent x2: " + extent1[1]);
        System.out.println("bound y1: " + bounds[2] + " - extent y1: " + extent1[2]);
        System.out.println("bound y2: " + bounds[3] + " - extent y2: " + extent1[3]);
        System.out.println("bound z1: " + bounds[4] + " - extent z1: " + extent1[4]);
        System.out.println("bound z2: " + bounds[5] + " - extent z2: " + extent1[5]);
        
        System.out.println("X´s axis length: " + xLength);
        System.out.println("Y´s axis length: " + yLength);
        System.out.println("Z´s axis length: " + zLength);
        
        vtkTriangleFilter triangulator = new vtkTriangleFilter();
        triangulator.SetInput(this.inputData.getPolyData());
        triangulator.Update();
       
        vtkCellLocator locator = new vtkCellLocator();
        //locator.SetDataSet(triangulator.GetOutput());
        locator.SetDataSet(triangulator.GetOutput());
        locator.BuildLocator();
       
        vtkPoints centerPoints = getCellCenters(extent1, resolution);
        
        int nrOfPoints = centerPoints.GetNumberOfPoints();
        double[] point = new double[3];
        int cellId;
        
        vtkPoints pointsInside = new vtkPoints();
                      
        for (int i = 0; i < nrOfPoints; ++i)
        {
            point = centerPoints.GetPoint(i);
            cellId = locator.FindCell(point);
            
            if (cellId >= 0)
            {
                pointsInside.InsertNextPoint(point);
            }            
        }
        
        vtkPolyData dataInside = new vtkPolyData();
        dataInside.SetPoints(pointsInside);
        
        vtkVertexGlyphFilter filter = new vtkVertexGlyphFilter();
        filter.SetInputConnection(dataInside.GetProducerPort());
        filter.Update();
        
        vtkPolyDataMapper pointsInsideMapper = new vtkPolyDataMapper();
        pointsInsideMapper.SetInput(filter.GetOutput());
        
        vtkPolyDataMapper inputMapper = new vtkPolyDataMapper();
        inputMapper.SetInput(this.inputData.getPolyData());
       
        pointsInsideActor = new vtkActor();
        pointsInsideActor.SetMapper(pointsInsideMapper);
        pointsInsideActor.GetProperty().SetPointSize(3);        
        pointsInsideActor.GetProperty().SetColor(0.00, 0.00, 255.00);  
        
        inputActor = new vtkActor();
        inputActor.SetMapper(inputMapper);
        inputActor.GetProperty().SetOpacity(0.5);
    }
    
    private vtkPoints getCellCenters(int[] extent, double resolution)
    {
        double shift = resolution / 2;
        double initialXCoord = extent[0] + shift;
        double initialYCoord = extent[2] + shift;
        double initialZCoord = extent[4] + shift;
        
                
        double[] center = new double[3];
        vtkPoints points = new vtkPoints();
        vtkCellArray cells = new vtkCellArray();
        int index = 0;
        
        double xIncrementor = initialXCoord;        
        
        while (xIncrementor < extent[1])
        {
            double yIncrementor = initialYCoord;
            
            while (yIncrementor < extent[3])
            {
                double zIncrementor = initialZCoord;
                
                while (zIncrementor < extent[5])
                {
                    center[0] = xIncrementor;
                    center[1] = yIncrementor;
                    center[2] = zIncrementor;
                    
                    points.InsertNextPoint(center);   
                    vtkVertex vertex = new vtkVertex();
                    vertex.GetPointIds().SetId(0, index);
                    cells.InsertNextCell(vertex);
                    vertex.Delete();                   
                    
                    zIncrementor += resolution;
                    index++;
                }
                
                yIncrementor += resolution;
            }
            
            xIncrementor += resolution;
        } 
        
        System.out.println("Nr. of Voxels: " + index);
        
        vtkPolyData centers = new vtkPolyData();
        centers.SetPoints(points);
        //points.Delete();
        centers.SetVerts(cells);
        
        return points;
    }
    
    private vtkPoints getCubesPoints(int[] extent, double resolution)
    {
        double initialXCoord = extent[0];
        double initialYCoord = extent[2];
        double initialZCoord = extent[4];
                     
        double[] cubeSourcePoint = new double[3];
        vtkPoints points = new vtkPoints();
        
        int index = 0;
        
        double xIncrementor = initialXCoord;        
        
        while (xIncrementor < extent[1])
        {
            double yIncrementor = initialYCoord;
            
            while (yIncrementor < extent[3])
            {
                double zIncrementor = initialZCoord;
                
                while (zIncrementor < extent[5])
                {
                    cubeSourcePoint[0] = xIncrementor;
                    cubeSourcePoint[1] = yIncrementor;
                    cubeSourcePoint[2] = zIncrementor;
                    
                    points.InsertPoint(index, cubeSourcePoint);   
                                       
                    zIncrementor += resolution;
                    index++;
                }
                
                yIncrementor += resolution;
            }
            
            xIncrementor += resolution;
        } 
        
        System.out.println("Number of Cubes´ points: " + index);
               
        return points;
    }
    
    private vtkUnstructuredGrid generateVoxels(int[] extent, double resolution)
    {
        vtkUnstructuredGrid grid = new vtkUnstructuredGrid();
        vtkPoints points = new vtkPoints();
        
        //int xLength = extent[1] - extent[0];
        int yLength = extent[3] - extent[2];
        int zLength = extent[5] - extent[4];
        
        double initialXCoord = extent[0];
        double initialYCoord = extent[2];
        double initialZCoord = extent[4];
                
        int index = 0;
        int offset = 0;
        int globalId = 0;
        
        int i = 0;
        double xIncrementor = initialXCoord;        
                
        while (xIncrementor < extent[1])
        {
            int j = 0;
            double yIncrementor = initialYCoord;
            
            while (yIncrementor < extent[3])
            {
                int k = 0;
                double zIncrementor = initialZCoord;
                
                while (zIncrementor < extent[5])
                {
                    // calculate points´ coordenates
                    double[][] vertices = generateVoxelPoints(xIncrementor, yIncrementor, zIncrementor, resolution);                    
                    // set the 8 voxel´s points
                    
                    for (int count = 0; count < vertices.length; ++count)
                    {
                        int pointId = globalId + count;
                        points.InsertPoint(pointId, vertices[count]);            
                    }
                    
                    vtkVoxel currentVoxel = new vtkVoxel();
                    
                    for (int count = 0; count < vertices.length; ++count)
                    {
                        int pointId = globalId + count;
                        currentVoxel.GetPointIds().SetId(count, pointId);            
                    }
                    
                    //setVoxelPoints(points, vertices);    
                    // calculate unique ID for voxels                   
                    offset = i * (yLength * zLength) + (j * yLength + k); 
                    // insert voxel into grid
                    //vtkVoxel currentVoxel = createVoxel(vertices.length, globalId);
                    grid.Allocate(1, 1);
                    grid.InsertNextCell(offset, currentVoxel.GetPointIds());
                    //System.out.println("offset: " + offset);
                    
                    zIncrementor += resolution;
                    globalId += 8;
                    ++index;
                    ++k;
                }
                
                yIncrementor += resolution;      
                ++j;
            }            
            
            xIncrementor += resolution;
            ++i;
        }    
        
        grid.SetPoints(points);
             
        System.out.println("Number of Voxels: " + index);
        System.out.println("Number of Points set: " + globalId);
                       
        return grid;
    }
    
    private double[][] generateVoxelPoints(double xIncrementor, 
                                           double yIncrementor, 
                                           double zIncrementor,
                                           double resolution)
    {
        // set 8 points to match with 8 voxel´s points
        double[][] pointsCoords = new double[8][3];
        
        pointsCoords[0] = new double[]{xIncrementor, yIncrementor, zIncrementor};
        pointsCoords[1] = new double[]{xIncrementor + resolution, yIncrementor, zIncrementor};
        pointsCoords[2] = new double[]{xIncrementor, yIncrementor + resolution, zIncrementor};
        pointsCoords[3] = new double[]{xIncrementor + resolution, yIncrementor + resolution, zIncrementor};
        pointsCoords[4] = new double[]{xIncrementor, yIncrementor, zIncrementor + resolution};
        pointsCoords[5] = new double[]{xIncrementor + resolution, yIncrementor, zIncrementor + resolution};
        pointsCoords[6] = new double[]{xIncrementor, yIncrementor + resolution, zIncrementor + resolution};
        pointsCoords[7] = new double[]{xIncrementor + resolution, yIncrementor + resolution, zIncrementor + resolution};
        
        return pointsCoords;
    }
    
    private int[] setVoxelPoints(vtkPoints points, double[][] vertices)
    {
        int[] ids = new int[vertices.length];
        
        for (int i = 0; i < vertices.length; ++i)
        {
            points.InsertNextPoint(vertices[i]);            
        }
        
        return ids;
    }
    
    
    private vtkVoxel createVoxel(int nrOfPoints, int globalId)
    {       
        vtkVoxel currentVoxel = new vtkVoxel();
        
        for (int i = 0; i < nrOfPoints; ++i)
        {
            int pointsId = globalId + i;
            currentVoxel.GetPointIds().SetId(i, pointsId);
            System.out.println("Current Voxel Point ID: " + pointsId);
        }
        
        return currentVoxel;
    }
    
    private void computeCrossingRays(double startPoint, 
                                     double endPoint, 
                                     double resolution, 
                                     vtkCellLocator locator)
    {
        vtkPoints pointsInside = new vtkPoints();
        vtkIdList idList = new vtkIdList();
               
        int rayID = 0;
        double zAcumulator = startPoint;               
       
        // generate lines parallel to x´ axis and perpendicular to y/z plane
        while (zAcumulator <= endPoint)
        {
            double yAcumulator = startPoint;
            
            while (yAcumulator <= endPoint)
            {                
                double[] p0 = new double[3];
                double[] p1 = new double[3];
                
                // start point
                p0[0] = startPoint;
                p0[1] = yAcumulator;
                p0[2] = zAcumulator;
                
                System.out.println(" coords[" + p0[0] + ", " + p0[1] + ", " + p0[2] + "]");
               
                // end point              
                p1[0] = endPoint;
                p1[1] = yAcumulator;
                p1[2] = zAcumulator;
                  
                System.out.println(" coords[" + p1[0] + ", " + p1[1] + ", " + p1[2] + "]");
                
                vtkPoints currentPoints = new vtkPoints();
                int cellID = locator.IntersectWithLine(p1, p0, currentPoints, idList);
                
                double test = 0.00;
                locator.FindCellsAlongLine(p0, p1, test, idList);
                
                if (idList.GetNumberOfIds() > 0)
                {
                    System.out.println("vra");
                }
                
                if (cellID > 0)                
                    System.out.println("Number of intersections with ray " + rayID + 
                                   " : " + currentPoints.GetNumberOfPoints());
                
                // copy array into global points
                // não sei se funciona: verificar
                pointsInside.ShallowCopy(currentPoints);
                 
                currentPoints.Delete();       
                             
                rayID += 1;
                yAcumulator += resolution;
            }
            
            zAcumulator += resolution;
        }        
    }
    
    private void visualizeFDTDGrid(int x1,
                                   int x2,
                                   int y1,
                                   int y2,
                                   int z1,
                                   int z2,
                                   double resolution
                                  )
    {
        //int dimLength
        vtkSphereSource sphereSource = new vtkSphereSource();
        sphereSource.SetCenter(0.00, 0.00, 0.00);
        sphereSource.SetRadius(5);
        sphereSource.SetThetaResolution(20);
        sphereSource.SetPhiResolution(20);
        sphereSource.Update();
                
        // TODO: create a uniform grid to intersect with object been modeled
        vtkImageData grid = new vtkImageData();
        grid.SetExtent(x1, x2, y1, y2, z1, z2);
        grid.SetSpacing(resolution, resolution, resolution);
        //grid.SetOrigin(-1.50, -1.50, -1.50);
        // grid.SetScalarTypeToDouble();
        grid.AllocateScalars();
        // grid.SetNumberOfScalarComponents(1);
        
        System.out.println();
        System.out.println("Number of Cells: " + grid.GetNumberOfCells());
        System.out.println("Number of Points: " + grid.GetNumberOfPoints());
        System.out.println();
    
        int[] dims = grid.GetDimensions();
        double[] spaces = grid.GetSpacing();
        
        System.out.println("Dimensions:");
        System.out.println("x: " + dims[0] + " y: " + dims[1] + " z: " + dims[2]);
        System.out.println();
        
        int[] extent = {x1, x2, y1, y2, z1, z2};
        
        vtkPoints centers = getCellCenters(extent, resolution);
        
//        vtkPolyDataMapper mapper = new vtkPolyDataMapper();
//        mapper.SetInput(centers);
        
        vtkAppendFilter appendFilter = new vtkAppendFilter();
        appendFilter.AddInput(grid);
        //appendFilter.AddInput(centers);
        appendFilter.Update();
                
        vtkDataSetMapper imageDataMapper = new vtkDataSetMapper();
        imageDataMapper.SetInputConnection(appendFilter.GetOutputPort());
        
//        vtkImageDataGeometryFilter gridFilter = new vtkImageDataGeometryFilter();
//        gridFilter.SetInput(grid);
//        gridFilter.Update();       
        
//        vtkPolyDataMapper gridMapper = new vtkPolyDataMapper();
//        gridMapper.SetInput(contourFilter.GetOutput());
        
        gridActor = new vtkActor();
        gridActor.SetMapper(imageDataMapper);
        //gridActor.SetMapper(mapper);
         //gridActor.GetProperty().SetRepresentationToWireframe();
        //gridActor.GetProperty().SetLineWidth(3.00);
        gridActor.GetProperty().SetPointSize(3.00);
        //gridActor.GetProperty().EdgeVisibilityOn();
        //gridActor.GetProperty().SetEdgeColor(0.00, 0.00, 0.00);
        //gridActor.GetProperty().SetLineWidth(2.00);      
    }
    
    private void generateFDTDGrid(int x1,
                                  int x2,
                                  int y1,
                                  int y2,
                                  int z1,
                                  int z2,
                                  double resolution
                                 )
    {
        //int dimLength
        vtkSphereSource sphereSource = new vtkSphereSource();
        sphereSource.SetCenter(0.00, 0.00, 0.00);
        sphereSource.SetRadius(5);
        sphereSource.SetThetaResolution(20);
        sphereSource.SetPhiResolution(20);
        sphereSource.Update();
        
        vtkPolyDataMapper sphereMapper = new vtkPolyDataMapper();
        sphereMapper.SetInput(sphereSource.GetOutput());
        
        inputActor = new vtkActor();
        inputActor.SetMapper(sphereMapper);
        inputActor.GetProperty().SetOpacity(0.5);
        
        vtkTriangleFilter triangulator = new vtkTriangleFilter();
        triangulator.SetInput(sphereSource.GetOutput());
        triangulator.Update();
        
        vtkCellLocator locator = new vtkCellLocator();
        locator.SetDataSet(triangulator.GetOutput());
        locator.BuildLocator();     
        
        int[] extent = {x1, x2, y1, y2, z1, z2};
        vtkPoints centers = getCellCenters(extent, resolution);
        
        vtkPoints pointsInside = new vtkPoints();
        vtkPolyData dataInside = new vtkPolyData();
        
        double[] point = new double[3];
        int nrOfPoints = centers.GetNumberOfPoints();
        
        for (int i = 0; i < nrOfPoints; ++i)
        {
            point = centers.GetPoint(i);
            int cellId = locator.FindCell(point);
            
            if (cellId >= 0)
            {
                System.out.println("Cell " + cellId + " is inside."); 
                pointsInside.InsertNextPoint(point);
            }
            else
            {
                System.out.println("Cell " + cellId + " is outside."); 
            }
        }
        
        dataInside.SetPoints(pointsInside);
        
        vtkVertexGlyphFilter vertexGlyph = new vtkVertexGlyphFilter();
        vertexGlyph.SetInputConnection(dataInside.GetProducerPort());
        
        vtkPolyDataMapper mapper = new vtkPolyDataMapper();
        mapper.SetInput(vertexGlyph.GetOutput());
                            
        gridActor = new vtkActor();
        gridActor.SetMapper(mapper);
        //gridActor.SetMapper(mapper);
         //gridActor.GetProperty().SetRepresentationToWireframe();
        //gridActor.GetProperty().SetLineWidth(3.00);
        gridActor.GetProperty().SetPointSize(3.00);
        gridActor.GetProperty().EdgeVisibilityOn();
        gridActor.GetProperty().SetEdgeColor(1.00, 0.00, 1.00);            
    }
    
    private void generateFDTDGrid2(int x1,
                                   int x2,
                                   int y1,
                                   int y2,
                                   int z1,
                                   int z2,
                                   double resolution
                                  )
    {       
        int[] extent = {x1, x2, y1, y2, z1, z2};     
        vtkUnstructuredGrid grid = generateVoxels(extent, resolution);
        
        vtkDataSetMapper gridMapper = new vtkDataSetMapper();
        gridMapper.SetInput(grid);
        
        gridActor = new vtkActor();
        gridActor.SetMapper(gridMapper);
        //cubeActor.GetProperty().SetRepresentationToWireframe();
    }
    
    // generate rays to intersect any object
    private vtkPolyData visualizeCrossingRays(double startPoint, double endPoint, double resolution)
    {
        vtkPoints points = new vtkPoints();
        vtkCellArray cells = new vtkCellArray();
        vtkPolyData polyData = new vtkPolyData();
        
        int pointID = -1;
        double zAcumulator = startPoint;               
       
        // generate lines parallel to x´ axis and perpendicular to y/z plane
        while (zAcumulator <= endPoint)
        {
            double yAcumulator = startPoint;
            
            while (yAcumulator <= endPoint)
            {                
                double[] p1 = new double[3];
                double[] p2 = new double[3];
                
                // start point
                p1[0] = startPoint;
                p1[1] = yAcumulator;
                p1[2] = zAcumulator;
                
                System.out.println(" coords[" + p1[0] + ", " + p1[1] + ", " + p1[2] + "]");
               
                // end point              
                p2[0] = endPoint;
                p2[1] = yAcumulator;
                p2[2] = zAcumulator;
                  
                System.out.println(" coords[" + p2[0] + ", " + p2[1] + ", " + p2[2] + "]");
                
                // create a vtkLine based on p1 and p2 points
                vtkLine currentLine = new vtkLine();
                
                // insert p1 and p2 to vtkPoints
                pointID++;
                points.InsertNextPoint(p1);
                // set line´s initial point
                currentLine.GetPointIds().SetId(0, pointID);
                pointID++;
                points.InsertNextPoint(p2);
                // set line´s end point
                currentLine.GetPointIds().SetId(1, pointID);     
                
                // insert current line into cell array
                cells.InsertNextCell(currentLine);
                
                yAcumulator += resolution;
            }
            
            zAcumulator += resolution;
        }
        
        polyData.SetPoints(points);
        polyData.SetLines(cells);
        points.Delete();
        cells.Delete();
        
        return polyData;
        
//        
//        vtkPolyDataMapper mapper = new vtkPolyDataMapper();
//        mapper.SetInput(polyData);
//        
//        linesActor = new vtkActor();
//        linesActor.SetMapper(mapper);  
//        //linesActor.GetProperty().SetLineWidth(2);
//        linesActor.GetProperty().SetColor(0.00, 0.00, 0.00);
    }

    /**     
     * @return the camera
     */
    public vtkCamera getCamera() 
    {
        return camera;
    }

    /**
     * @param camera the camera to set
     */
    public final void setCamera() 
    {
        camera = new vtkCamera();
        camera.SetViewUp(0.00, 1.00, 0.00);
        camera.SetPosition(2, 2, 2);
        camera.SetFocalPoint(0, 0, 0);
    }

    /**
     * @return the panel
     */
    public vtkPanel getPanel() 
    {
        return panel;
    }

    /**
     * @param panel the panel to set
     */
    public final void setPanel() 
    {
        this.panel = new vtkPanel();
        this.panel.GetRenderer().SetBackground(255.00, 255.00, 255.00);
        this.panel.GetRenderer().AddActor(inputActor);
        //this.panel.GetRenderer().AddActor(smallSphereActor);
        this.panel.GetRenderer().AddActor(pointsInsideActor);
        //this.panel.GetRenderer().AddActor(outlineActor);
        //this.panel.GetRenderer().AddActor(surfaceActor);
        //panel.GetRenderer().AddActor(linesActor);
        //panel.GetRenderer().AddActor(gridActor);
        //panel.GetRenderer().AddActor(cubeActor);
        this.panel.GetRenderer().SetActiveCamera(camera);
    }
    
    private static void LoadVTKLibraries()
    {
        System.loadLibrary("vtkCommon");
        System.loadLibrary("vtkFiltering");
        System.loadLibrary("vtkGenericFiltering");
        System.loadLibrary("vtkGraphics");
        System.loadLibrary("vtkHybrid");
        System.loadLibrary("vtkImaging");
        System.loadLibrary("vtksys");
        System.loadLibrary("vtkexpat");
        System.loadLibrary("vtkfreetype");
        System.loadLibrary("vtkftgl");
        System.loadLibrary("vtkjpeg");
        System.loadLibrary("vtkzlib");
        System.loadLibrary("vtktiff");
        //System.loadLibrary("vtkMPEG2Encode");
        System.loadLibrary("vtkpng");
        System.loadLibrary("vtkDICOMParser");
        System.loadLibrary("vtkIO");
        System.loadLibrary("vtkRendering");
        System.loadLibrary("vtkVolumeRendering");
        System.loadLibrary("vtkCommonJava");
        System.loadLibrary("vtkFilteringJava");
        System.loadLibrary("vtkGenericFilteringJava");
        System.loadLibrary("vtkGraphicsJava");
        System.loadLibrary("vtkHybridJava");
        System.loadLibrary("vtkImagingJava");
        System.loadLibrary("vtkIOJava");
        System.loadLibrary("vtkGraphicsJava");
        System.loadLibrary("vtkRenderingJava");
        System.loadLibrary("vtkVolumeRenderingJava");
    }
}
